using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using XLua;

public class EventListener : Singleton<EventListener>
{
    private Dictionary<int, Delegate> _dictEvent = new Dictionary<int, Delegate>();
    private Dictionary<int, ListExt<ILuaFunction>> _dictLua = new Dictionary<int, ListExt<ILuaFunction>>();

    private int _temp;

    public GameObject curSelectObj;

    public EventSystem es;

    public static EventListener getInstance()
    {
        return Instance;
    }

    public static void Bind<T>(int type, DelegateDef.EventCallBack<T> callBack)
    {
        if (Instance._dictEvent.ContainsKey(type))
        {
            Instance._dictEvent[type] = (DelegateDef.EventCallBack<T>)Instance._dictEvent[type] + callBack;
        }
        else
        {
            Instance._dictEvent[type] = callBack;
        }
    }

    public static void BindLua(int type, ILuaFunction callBack)
    {
        ListExt<ILuaFunction> lst;
        if (Instance._dictLua.TryGetValue(type, out lst))
        {
            lst.Add(callBack);
        }
        else
        {
            lst = new ListExt<ILuaFunction>(1);
            lst.Add(callBack);
            Instance._dictLua[type] = lst;
        }
    }

    public static void Broadcast<T>(int type, T data = default(T))
    {
        Delegate dlg;
        if (Instance._dictEvent.TryGetValue(type, out dlg))
        {
            if (dlg != null)
            {
                Delegate[] arr = dlg.GetInvocationList();
                if (arr != null)
                {
                    Instance._temp = arr.Length;
                    for (int i = Instance._temp - 1; i >= 0; i--)
                    {
                        ((DelegateDef.EventCallBack<T>)arr[i]).Invoke(data);
                    }
                }
            }
        }

        ListExt<ILuaFunction> arrLua;
        if (Instance._dictLua.TryGetValue(type, out arrLua))
        {
            if (arrLua != null)
            {
                Instance._temp = arrLua.Count;
                if (Instance._temp > 0)
                {
                    for (int i = Instance._temp - 1; i >= 0; i--)
                    {
                        arrLua.list[i].Call(data);
                    }
                }
            }
        }
    }

    public static bool IsContainEvent(int type)
    {
        return Instance._dictEvent.ContainsKey(type) || Instance._dictLua.ContainsKey(type);
    }

    public static void Remove<T>(int type, DelegateDef.EventCallBack<T> callBack = null)
    {
        if (Instance._dictEvent != null && Instance._dictEvent.ContainsKey(type))
        {
            if (callBack == null)
            {
                Instance._dictEvent.Remove(type);
            }
            {
                Instance._dictEvent[type] = (DelegateDef.EventCallBack<T>)Instance._dictEvent[type] - callBack;
            }
        }
    }

    public static void RemoveLua(int type, ILuaFunction callBack = null)
    {
        if (Instance._dictLua.ContainsKey(type))
        {
            if (callBack == null)
            {
                Instance._dictLua.Remove(type);
            }
            else
            {
                Instance._dictLua[type].Remove(callBack);
                LuaHelper.DisposeLuaFunction(callBack);
            }
        }
    }

    public void Clear()
    {
        _dictEvent.Clear();
        List<ILuaFunction> arrLua;

        foreach (int key in _dictEvent.Keys)
        {
            if (_dictEvent[key] == null)
                continue;
            arrLua = _dictLua[key].GetList();
            if (arrLua == null)
                continue;
            for (int i = arrLua.Count - 1; i >= 0; i--)
            {
                arrLua[i].DisposeLuaFunction();
            }
            _dictLua[key].Clear();
        }
        _dictLua.Clear();
    }

    public override void Dispose()
    {
        base.Dispose();
        Clear();
    }
}